// SongTCPSocketDll.cpp

#include "stdafx.h"
#include "FrameBufferQueue.h"
#include <crtdbg.h>
#include <malloc.h>

FrameBufferQueue::FrameBufferQueue(int nPreallocSize)
    : m_ppVoid(NULL)
    , m_nCount(0)
    , m_nAllocated(nPreallocSize)
{
    ASSERT(nPreallocSize>=0);

    if (nPreallocSize > 0)
    {
        m_ppVoid = static_cast<LPVOID*>(malloc(nPreallocSize * sizeof(LPVOID)));
    }
}

FrameBufferQueue::FrameBufferQueue(const FrameBufferQueue& src)
    : m_ppVoid(NULL)
    , m_nCount(0)
    , m_nAllocated(0)
{
    for (int index = 0; index < src.GetSize(); index++)
    {
        Add(src.GetAt(index));
    }
}

FrameBufferQueue::~FrameBufferQueue()
{
    if (m_ppVoid != NULL)
    {
        free(m_ppVoid);
    }
}

void FrameBufferQueue::Empty()
{
    if (m_ppVoid != NULL)
    {
        free(m_ppVoid);
    }

    m_ppVoid = NULL;
    m_nCount = m_nAllocated = 0;
}

void FrameBufferQueue::Resize(int iSize)
{
    Empty();

    m_ppVoid = static_cast<LPVOID*>(malloc(iSize * sizeof(LPVOID)));

    ::ZeroMemory(m_ppVoid, iSize * sizeof(LPVOID));

    m_nAllocated = iSize;
    m_nCount = iSize;
}

bool FrameBufferQueue::IsEmpty() const
{
    return m_nCount == 0;
}

bool FrameBufferQueue::Add(LPVOID pData)
{
    if (++m_nCount >= m_nAllocated)
    {
        int nAllocated = m_nAllocated * 2;

        if (nAllocated == 0)
        {
            nAllocated = 11;
        }

        LPVOID* ppVoid = static_cast<LPVOID*>(realloc(m_ppVoid, nAllocated * sizeof(LPVOID)));

        if (ppVoid != NULL)
        {
            m_nAllocated = nAllocated;
            m_ppVoid     = ppVoid;
        }
        else
        {
            --m_nCount;

            return false;
        }
    }

    m_ppVoid[m_nCount - 1] = pData;

    return true;
}

bool FrameBufferQueue::InsertAt(int iIndex, LPVOID pData)
{
    if (iIndex == m_nCount)
    {
        return Add(pData);
    }

    if (iIndex < 0 || iIndex > m_nCount)
    {
        return false;
    }

    if (++m_nCount >= m_nAllocated)
    {
        int nAllocated = m_nAllocated * 2;

        if (nAllocated == 0)
        {
            nAllocated = 11;
        }

        LPVOID* ppVoid = static_cast<LPVOID*>(realloc(m_ppVoid, nAllocated * sizeof(LPVOID)));

        if (ppVoid != NULL)
        {
            m_nAllocated = nAllocated;
            m_ppVoid     = ppVoid;
        }
        else
        {
            --m_nCount;

            return false;
        }
    }

    memmove(&m_ppVoid[iIndex + 1], &m_ppVoid[iIndex], (m_nCount - iIndex - 1) * sizeof(LPVOID));

    m_ppVoid[iIndex] = pData;

    return true;
}

bool FrameBufferQueue::SetAt(int iIndex, LPVOID pData)
{
    if (iIndex < 0 || iIndex >= m_nCount)
    {
        return false;
    }

    m_ppVoid[iIndex] = pData;

    return true;
}

bool FrameBufferQueue::Remove(int iIndex)
{
    if (iIndex < 0 || iIndex >= m_nCount)
    {
        return false;
    }
    if (iIndex < --m_nCount )
    {
        ::CopyMemory(m_ppVoid + iIndex, m_ppVoid + iIndex + 1, (m_nCount - iIndex) * sizeof(LPVOID));
    }

    return true;
}

int FrameBufferQueue::Find(LPVOID pData) const
{
    for (int index = 0; index < m_nCount; index++)
    {
        if (m_ppVoid[index] == pData)
        {
            return index;
        }
    }

    return -1;
}

int FrameBufferQueue::GetSize() const
{
    return m_nCount;
}

LPVOID* FrameBufferQueue::GetData()
{
    return m_ppVoid;
}

LPVOID FrameBufferQueue::GetAt(int iIndex) const
{
    if (iIndex < 0 || iIndex >= m_nCount)
    {
        return NULL;
    }

    return m_ppVoid[iIndex];
}

LPVOID FrameBufferQueue::operator[](int iIndex) const
{
    ASSERT(iIndex>=0 && iIndex<m_nCount);

    return m_ppVoid[iIndex];
}

bool FrameBufferQueue::EnQueue(LPVOID pData)
{
    return Add(pData);
}

LPVOID FrameBufferQueue::DeQueue()
{
    LPVOID pData = GetAt(0);

    Remove(0);

    return pData;
}
